package com.sk.rpcAssist.dataManager;

import com.sk.rpcAssist.consumerAssist.AbstractConsumerAstStrategy;
import com.sk.rpcAssist.domain.BasicConfig;
import com.sk.rpcAssist.domain.ProvideInfoValue;
import com.sk.rpcAssist.domain.ServiceType;
import com.sk.rpcAssist.io.protocol.RpcRequest;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.recipes.cache.ChildData;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;

import java.net.InetSocketAddress;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * description：消费端管理生产者信息默认实现
 *
 * @author 孙文斌
 * @Date: 2021/2/5 16:55
 */
@Data
@Slf4j
public class DefaultConsumerDataManager implements ConsumerDataManager {

    private ConsumerCuratorClient curatorClient;
    //本地缓存zk上provide的信息
    private static ConcurrentHashMap<Integer, ProvideInfoValue> provideInfoMap = new ConcurrentHashMap();

    public DefaultConsumerDataManager() {
        this.curatorClient = new ConsumerCuratorClient(this);

    }

    @Override
    public void addServerInfo(ProvideInfoValue provideInfoValue) {
        provideInfoMap.put(keyString(provideInfoValue), provideInfoValue);
    }

    @Override
    public void delServerInfo(ProvideInfoValue provideInfoValue) {
        provideInfoMap.remove(keyString(provideInfoValue));
    }

    @Override
    public void updateServerInfo(ProvideInfoValue provideInfoValue) {
        provideInfoMap.put(keyString(provideInfoValue), provideInfoValue);
    }

    @Override
    public ProvideInfoValue findServerInfo(ProvideInfoValue rpcRequest) {
        return provideInfoMap.get(keyString(rpcRequest));
    }

    @Override
    public synchronized void synData(List<ChildData> childDataList, PathChildrenCacheEvent event) {
        //TODO:使用线程池异步处理
        log.info("zookeeper call is invoke ,event is " + event.toString());
        try {
            ChildData data = event.getData();
            switch (event.getType()) {
                case CHILD_ADDED:
                    log.info("服务上线");
                    processData(event);
                    break;
                case CHILD_UPDATED:
                    log.info("服务更新");
                    processData(event);
                    break;
                case CHILD_REMOVED:
                    log.info("服务删除");
                    processData(event);
                    break;
                default:
                    break;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
    private Integer keyString(ProvideInfoValue value){
        RpcRequest rpcRequest= value.getRpcRequest();
        Class<?>[] parameterTypes  =rpcRequest.getParameterTypes();
        StringBuilder sb = new StringBuilder();
        for (Class<?> parameterType : parameterTypes) {
            sb.append(parameterType.getName());
        }
        int hashCode = sb.toString().hashCode();
        String key = "/"+rpcRequest.getClassName()+"/provider/"+rpcRequest.getMethodName()+hashCode;
        return key.hashCode();
    }

    private void processData(PathChildrenCacheEvent event) {
        try {
            PathChildrenCacheEvent.Type type = event.getType();
            ChildData data = event.getData();
            String path = data.getPath();
            int i = path.lastIndexOf("/");
            String[] arr = path.split("/");
            String[] address = arr[arr.length - 1].split(":");
            String k = path.substring(0, i);
            int keyValue = k.hashCode();
            //todo:处理编码协议部分
            String protocolCode = new String(data.getData() != null ? data.getData() : new byte[1], "UTF-8");
            //新增逻辑
            if (type == PathChildrenCacheEvent.Type.CHILD_ADDED) {
                ProvideInfoValue provideInfoValue = new ProvideInfoValue(address[0], Integer.valueOf(address[1]), null, null);
                provideInfoMap.put(keyValue, provideInfoValue);
            }
            //更新逻辑
            if (type == PathChildrenCacheEvent.Type.CHILD_UPDATED) {

            }
            //删除逻辑
            if (type == PathChildrenCacheEvent.Type.CHILD_REMOVED) {
                provideInfoMap.remove(keyValue);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
